#include "ExchangeAdapterConfig.h"
#include "RMMSMarketRouter.h"
#include "DebugUtils.h"
#include "ExchangeAdapterCompiler.h"

RMMS_NS_BEGIN

const tchar *g_pmarketrouterxml = "RMMSMarketRouter.xml";

RMMSMarketRouter::RMMSMarketRouter():m_recvmutexs(),m_fixacceptor(),m_gateway(),
	m_binit(false)
{
	std::memset(&m_exchpara,0,sizeof(RMMSMarketGatewayPara));
}

RMMSMarketRouter::~RMMSMarketRouter(){}

int32 RMMSMarketRouter::GetXMLExchCfg(Exchange exch,
	TiXmlNode *pExchNode,RMMSMarketGatewayPara *pgatewaypara)
{
	const tchar *pxmltype = "type";
	const tchar *pxmlpara = "para";
	const tchar *pxmldllname = "dllname";
	const tchar *pxmlexchname = "exchname";
	TiXmlElement *pelement = NULL;

	pelement = pExchNode->FirstChildElement(pxmltype);
	if(0 == std::strcmp("XML",pelement->GetText()))
		pgatewaypara->exchpara[exch].type = RMMS_NS::XML;
	else
		return -1;

	pelement = pExchNode->FirstChildElement(pxmlpara);
	pgatewaypara->exchpara[exch].para = pelement->GetText();

	pelement = pExchNode->FirstChildElement(pxmldllname);
	pgatewaypara->exchpara[exch].dllname = pelement->GetText();

	pelement = pExchNode->FirstChildElement(pxmlexchname);

	return 0;
}

void RMMSMarketRouter::FreeExchAdapter()
{
}

int32 RMMSMarketRouter::InitRouterPara(RMMSMarketGatewayPara *pgatewaypara,
	RMMSFixAcceptorPara *pfixacceptorpara)
{
	const tchar *psubname = "supportexchs";
	const tchar *pexchname = "exchange";
	const tchar *pfixnodename = "FixAcceptor";
	const tchar *pcfgname = "cfgname";

	TiXmlDocument doc(g_pmarketrouterxml);
	if (!doc.LoadFile())
		return -1;

	TiXmlNode *pExchNode = NULL,*pFixNode = NULL,*pTmpNode = NULL;
	TiXmlElement *pRootElement = NULL,*pTmpElement = NULL;
	RMMS_NS::Exchange exch;

	pRootElement = doc.RootElement();

	pFixNode = pRootElement->FirstChild(pfixnodename);
	pTmpElement = pFixNode->FirstChildElement(pcfgname);
	pfixacceptorpara->cfgname = pTmpElement->GetText();

	pTmpNode = pRootElement->FirstChild(psubname);
	pTmpNode = pTmpNode->FirstChild(pexchname);
	for (;pTmpNode != NULL;pTmpNode = pTmpNode->NextSibling(pexchname)){
		pTmpElement = dynamic_cast<TiXmlElement*>(pTmpNode);

		if(0 == std::strcmp("DCE",pTmpElement->GetText()))
			exch = RMMS_CN_DL;
		else if (0 == std::strcmp("ZCE",pTmpElement->GetText()))
			exch = RMMS_CN_ZZ;
		else if (0 == std::strcmp("SHFE",pTmpElement->GetText()))
			exch = RMMS_CN_SH;
		else if (0 == std::strcmp("CFFEX",pTmpElement->GetText()))
			exch = RMMS_CN_ZJ;
		else if (0 == std::strcmp("CME",pTmpElement->GetText()))
			exch = RMMS_US_CME;
		else if (0 == std::strcmp("KSFT",pTmpElement->GetText()))
			exch = RMMS_CN_KSFT;
		else if (0 == std::strcmp("RMMS",pTmpElement->GetText()))
			exch = RMMS_CN_RMMS;
		else
			exch = RMMS_EXCH_UNKNOWN;

		if(RMMS_EXCH_UNKNOWN == exch)
			return -1;

		pgatewaypara->exchpara[exch].bAllowedStart = true;
		pExchNode = pRootElement->FirstChild(pTmpElement->GetText());
		if(0 > GetXMLExchCfg(exch,pExchNode,pgatewaypara))
			return -1;
	}
	return 0;
}

int32 RMMSMarketRouter::InitFixAcceptor(RMMSFixAcceptorPara *pfixacceptorpara)
{
	try{
		m_seids = m_fixacceptor.InitSession(pfixacceptorpara->cfgname);
	} catch(...){
		std::cout<<"FIX Acceptor Config Initialize Exception!"<<std::endl;
		return -1;
	}

	if (0 >= m_seids.size())
		return -1;
	return m_fixacceptor.Init();
}

int32 RMMSMarketRouter::InitExchAdapter()
{
	for (int32 i = 0; i < (int32)RMMS_EXCH_SUM;i++){
		Exchange exch = (Exchange)i;
		m_exchpara.exchpara[exch].presponse = this;
	}

	if(0 > m_gateway.Init(m_exchpara,&m_initexchs))
		return -1;
	
	return 0;
}

void RMMSMarketRouter::UninitRouterPara(RMMSMarketGatewayPara *pgatewaypara)
{
	std::memset(pgatewaypara,0,sizeof(*pgatewaypara));
}

void RMMSMarketRouter::UninitFixAcceptor()
{
	m_fixacceptor.Uninit();
}

void RMMSMarketRouter::UninitExchAdapter()
{
	m_gateway.Uninit(&m_initexchs);
	FreeExchAdapter();
}

int32 RMMSMarketRouter::Init()
{
	if(0 > InitRouterPara(&m_exchpara,&m_fixpara))
		return -1;
	if(0 > InitFixAcceptor(&m_fixpara)){
		UninitRouterPara(&m_exchpara);
		return -1;
	}
	if(0 > InitExchAdapter()){
		UninitFixAcceptor();
		UninitRouterPara(&m_exchpara);
		return -1;
	}

	m_binit = true;
	return 0;
}

void RMMSMarketRouter::Uninit()
{
	m_binit = false;
	UninitExchAdapter();
	UninitFixAcceptor();
	UninitRouterPara(&m_exchpara);
}

int32 RMMSMarketRouter::Start()
{
	if(!m_binit)
		return -1;

	if(0 > m_fixacceptor.Start())
		return -1;

	std::map<Exchange,bool>::iterator it = m_initexchs.begin();
	for (;it != m_initexchs.end();it++){
		switch(it->first){
		case RMMS_CN_SH:
		case RMMS_CN_ZJ:
			break;
		default:
			StartExch(it->first);
			break;
		}
	}

	return 0;
}

void RMMSMarketRouter::Stop()
{
	std::map<Exchange,bool>::iterator it = m_initexchs.begin();
	for (;it != m_initexchs.end();it++){
		if(false == it->second)
			continue;
		m_gateway.LogoutExch(it->first,NULL,&m_initexchs);
	}
	m_fixacceptor.Stop();
}

int32 RMMSMarketRouter::StartExch(Exchange exch)
{
	if(m_initexchs.end() == m_initexchs.find(exch))
		return -1;
	if(true == m_initexchs[exch])
		return 1;
	if(0 > m_gateway.LoginExch(exch,NULL,&m_initexchs))
		return -1;
	return 0;
}

void RMMSMarketRouter::StopExch(Exchange exch)
{
	if(m_initexchs.end() == m_initexchs.find(exch))
		return;
	if(false == m_initexchs[exch])
		return;
	m_gateway.LogoutExch(exch,NULL,&m_initexchs);
}

void RMMSMarketRouter::MsgResponse(Exchange exch,const FIX::Message& msg)
{
	LIB_NS::Locker locker(m_recvmutexs[exch]);
	std::set<FIX::SessionID>::iterator it;
	for (it = m_seids.begin();it != m_seids.end();it++){
		RMMSFixAcceptor::SendMsg(*const_cast<FIX::SessionID*>(&(*it)),
			*const_cast<FIX::Message*>(&msg));
	}
}

void RMMSMarketRouter::AdmEvent_NetConnect(Exchange exch)
{
	switch(exch){
	case RMMS_CN_SH:
	case RMMS_CN_ZJ:
		StartExch(exch);
		break;
	default:
		break;
	}
}

void RMMSMarketRouter::AdmEvent_NetDisConnect(Exchange /*exch*/)
{
}

void RMMSMarketRouter::AdmEvent_NetLogon(Exchange /*exch*/)
{
}

void RMMSMarketRouter::AdmEvent_NetLogout(Exchange /*exch*/)
{

}

RMMS_NS_END